#ifndef __COMMUNICATION_H__
#define __COMMUNICATION_H__

typedef unsigned short      uint16;

#define SUCCESS 1
#define FAULT   0
#define FAIL    0
#ifndef TRUE
#define TRUE    1
#endif

#define IP_ADDR     "192.168.31.106"
#define SERVER_PORT 8888
#define BACKLOG     10

/*将两个一字节的变量构成一个两字节的变量*/
#define BUILD_UINT16(loByte, hiByte) \
          ((uint16)(((loByte) & 0x00FF) + (((hiByte) & 0x00FF) << 8)))
/*将一个两字节的变量拆分为两个一字节的变量*/
#define HI_UINT16(a) (((a) >> 8) & 0xFF)
#define LO_UINT16(a) ((a) & 0xFF)

/*帧头*/
#define DATA_HEADER_FIRST                   0x5A
#define DATA_HEADER_SECOND                  0x5A
/*ACK ERROR 应答错误宏定义*/  
#define ACK_OK                              0x00
#define ACK_RECV_HEAD_FIRST_ERR             0xE1 
#define ACK_RECV_HEAD_SECOND_ERR            0xE2
#define ACK_RECV_LENGTH_ERR                 0xE3  
#define ACK_RECV_LRC_ERR                    0xE4

/*通用应答*/
#define WRONG_CMD_TYPE_ACK                  0xFE

/*登陆相关部分*/
/*命令类型*/
#define LOGIN_CMD_TYPE                      0xA0
/*命令*/
#define LOGIN_CMD                           0x01
#define REGISTER_CMD                        0x02
/*ACK*/
#define REGISTER_SUCCESS_ACK                0x00
#define REGISTER_USER_REPEAT_ERR_ACK        0x01
#define LOGIN_SUCCESS_ACK                   0x02
#define LOGIN_NO_MATCH_ERR_ACK              0x03

/*车票相关部分*/
/*命令类型*/
#define TICKET_CMD_TYPE                     0xA1
/*命令*/
#define FIND_TICKET_CMD                     0x03
#define BUY_TICEKT_CMD                      0x04
#define FIND_ORDER_CMD                      0x05
#define RETURN_TICKET_CMD                   0x06
#define ADMIN_ADD_TICEKT                    0x09
#define ADMIN_CHANGE_TICKET                 0x12
#define ADMIN_ADD_USER                      0x11
#define ADMIN_CHANGE_USER                   0x14
#define ADMIN_ALL_ORDER                     0x08
#define ADMIN_ALL_USER                      0x10
#define ADMIN_DELETE_USER                   0x15
#define ADMIN_DELETE_TICKET                 0x13
#define CHANGE_FIND_TICKET_CMD              0x16
#define USER_FIND_TICKET                    0x17
#define DESTROY_CMD                         0x19

/*ACK*/
#define BUY_TICEKT_SUCCESS_ACK              0x04
#define RETURN_TICKET_SUCCESS_ACK           0x05
#define NO_FIND_TICKET_ACK                  0x07
#define ADD_TICKET_SUCCESS_ACK              0x08
#define ADD_TICKET_FALSE_ACK                0x09
#define ADD_USER_SUCCESS_ACK                0x10
#define ADD_USER_FALSE_ACK                  0x11
#define ADMIN_CHANGE_TICKET_SUCCESS_ACK     0x12
#define ADMIN_CHANGE_TICKET_FALSE_ACK       0x13
#define ADMIN_DELETE_TICKET_SUCCESS_ACK     0x14
#define ADMIN_DELETE_TICKET_FALSE_ACK       0x15
#define ADMIN_CHANGE_USER_SUCCESS_ACK       0x16
#define ADMIN_CHANGE_USER_FALSE_ACK         0x17
#define ADMIN_DELETE_USER_SUCCESS_ACK       0x18
#define ADMIN_DELETE_USER_FALSE_ACK         0x19
#define NO_TICKET_NUM_ACK                   0x20
#define REPEAT_ACK                          0x21

/*心跳包相关部分*/
/*命令类型*/
#define HEART_CMD_TYPE                      0xA2
/*命令*/
#define HEART_CMD                           0x18

#define DATA_MAX_NUM  30
struct data_packet {
  char cmd_type;
	char cmd;/*操作命令*/
	char ack;/*应答*/
	char *data[DATA_MAX_NUM];/*数据*/
};

enum {
    COMM_PARAM_NULL = 1,
    COMM_RECV_BYTE_ERR,
    COMM_ANAYL_HEAD_FIRST_ERR,
    COMM_ANAYL_HEAD_SECOND_ERR,
    COMM_ANAYL_LENGTH_ERR,
    COMM_ANAYL_LRC_ERR,
    COMM_SEND_ERR,
    COMM_RECV_ACK_ERR,
    COMM_CMD_OVERSTEP_ERR,
    COMM_FUNC_NULL_ERR,
    COMM_GET_FD_ERR,
    COMM_BIND_ERR,
    COMM_LISTEN_ERR,
    COMM_DATA_FIELD_LENGTH_ERR,
    COMM_GET_HOST_NAME_ERR,
    COMM_CONNECT_ERR,
    COMM_GET_ACK,
    COMM_CLIENT_DISCONNECT,//18
};

enum {
  FREE = 0,
  ANALY_HEAD,
  ANALY_LEN,
  ANALY_DATA,
  ANALY_DONE,
};

extern int sever_communication_init(void);
extern int recv_data(int recvfd, char **data, uint16 *length);
extern int send_data(int sendfd, char *data, uint16 length);
extern int package_data(struct data_packet *p_data_packet, 
                		char **data, uint16 *length);
extern int analy_data(struct data_packet *p_data_packet, 
                	  char *data, uint16 length); 
extern void send_ack(int sendfd, char error); 


#endif